#include <gtest/gtest.h>
#include "../../lexer.h"

class LexerTest : public ::testing::Test
{
public:
    void SetUp() override
    {
        static llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> buf = llvm::MemoryBuffer::getFile("../testset/lexer_01.txt");
        if (!buf)
        {
            llvm::errs() << "can't open file!\n";
            return;
        }
        llvm::SourceMgr mgr;
        DiagEngine diagEngine(mgr);
        mgr.AddNewSourceBuffer(std::move(*buf), llvm::SMLoc());
        lexer = new Lexer(diagEngine, mgr);
    }

    void TearDown() override
    {
        delete lexer;
    }

    Lexer *lexer;
};

/*
int a = 3, b = 5;
a + 3 * b - 6;
*/
TEST_F(LexerTest, NextToken)
{
    std::vector<Token> expectedVec; // 正确集
    std::vector<Token> curVec;      // 当前集
    expectedVec.push_back(Token{TokenType::kw_int, 1, 1});
    expectedVec.push_back(Token{TokenType::indentifier, 1, 5});
    expectedVec.push_back(Token{TokenType::equal, 1, 7});
    expectedVec.push_back(Token{TokenType::number, 1, 9});
    expectedVec.push_back(Token{TokenType::comma, 1, 10});
    expectedVec.push_back(Token{TokenType::indentifier, 1, 12});
    expectedVec.push_back(Token{TokenType::equal, 1, 14});
    expectedVec.push_back(Token{TokenType::number, 1, 16});
    expectedVec.push_back(Token{TokenType::semi, 1, 17});
    expectedVec.push_back(Token{TokenType::indentifier, 2, 1});
    expectedVec.push_back(Token{TokenType::plus, 2, 3});
    expectedVec.push_back(Token{TokenType::number, 2, 5});
    expectedVec.push_back(Token{TokenType::star, 2, 7});
    expectedVec.push_back(Token{TokenType::indentifier, 2, 9});
    expectedVec.push_back(Token{TokenType::minus, 2, 11});
    expectedVec.push_back(Token{TokenType::number, 2, 13});
    expectedVec.push_back(Token{TokenType::semi, 2, 14});

    Token token;
    while(true)
    {
        lexer->NextToken(token);
        if(token.tokenType == TokenType::eof)
        {
            break;
        }
        curVec.push_back(token);
    }

    ASSERT_EQ(expectedVec.size(), curVec.size());
    for(int i = 0; i < expectedVec.size(); i++)
    {
        const auto expected_tok = expectedVec[i];
        const auto cur_tok = curVec[i];

        EXPECT_EQ(expected_tok.tokenType, cur_tok.tokenType);
        EXPECT_EQ(expected_tok.row, cur_tok.row);
        EXPECT_EQ(expected_tok.col, cur_tok.col);
    }
}